// Copyright 2013 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.api.ads.dfa.matchtables;

import com.google.api.ads.dfa.axis.factory.DfaServices;
import com.google.api.ads.dfa.axis.v1_20.AdBase;
import com.google.api.ads.dfa.axis.v1_20.ApiException;
import com.google.api.ads.dfa.axis.v1_20.CreativeBase;
import com.google.api.ads.dfa.axis.v1_20.Size;
import com.google.api.ads.dfa.axis.v1_20.SizeRecordSet;
import com.google.api.ads.dfa.axis.v1_20.SizeRemote;
import com.google.api.ads.dfa.axis.v1_20.SizeSearchCriteria;
import com.google.api.ads.dfa.lib.client.DfaSession;

import java.rmi.RemoteException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Helper class that can be used to make secondary look ups for size IDs found in either
 * creative or ad results.
 *
 * @author Moshe Kahan
 */
public class SizeLookupHelper {

  private final SizeRemote sizeService;
  private Map<Long, String> sizeMap;

  SizeLookupHelper(DfaServices dfaServices, DfaSession session) {
    this(dfaServices.get(session, SizeRemote.class));
  }

  SizeLookupHelper(SizeRemote sizeService) {
    this.sizeService = sizeService;
    this.sizeMap = new HashMap<Long, String>();
  }

  void retrieveCreativeSizes(List<CreativeBase> results) throws DfaRemoteException {
    Set<Long> newSizes = new HashSet<Long>();
    for (CreativeBase entity : results) {
      long sizeId = entity.getSizeId();
      if (sizeId > 0 && !sizeMap.containsKey(sizeId)) {
        sizeMap.put(sizeId, "");
        newSizes.add(sizeId);
      }
    }
    retrieveSizes(newSizes);
  }

  void retrieveAdSizes(List<AdBase> results) throws DfaRemoteException {
    Set<Long> newSizes = new HashSet<Long>();

    for (AdBase entity : results) {
      long sizeId = entity.getSizeId();
      if (sizeId > 0 && !sizeMap.containsKey(sizeId)) {
        sizeMap.put(sizeId, "");
        newSizes.add(sizeId);
      }
    }
    retrieveSizes(newSizes);
  }

  String getSize(long sizeId) {
    return sizeMap.get(sizeId);
  }

  private void retrieveSizes(Set<Long> newSizes) throws DfaRemoteException {
    // Secondary lookup of sizes.
    if (!newSizes.isEmpty()) {
      SoapLookup<Size> sizeSoapLookup = new SoapLookup<Size>(newSizes,
          new SizeSoapLookupCallback());
      while (sizeSoapLookup.hasNext()) {
        Size result = sizeSoapLookup.next();
        String sizeString = result.getWidth() + "x" + result.getHeight();
        sizeMap.put(result.getId(), sizeString);
      }
    }
  }

  private class SizeSoapLookupCallback implements SoapLookupCallback<Size> {
    public int getRecords(long[] ids, List<Size> recordList)
        throws ApiException, RemoteException {
      // Retrieve the sizes
      SizeSearchCriteria sizeSearchCriteria = new SizeSearchCriteria();
      if (ids != null) {
        sizeSearchCriteria.setIds(ids);
      }
      sizeSearchCriteria.setWidth(-1);
      sizeSearchCriteria.setHeight(-1);
      SizeRecordSet sizeRecordSet = sizeService.getSizes(sizeSearchCriteria);
      Size[] sizeArray = sizeRecordSet.getRecords();
      for (Size size : sizeArray) {
        recordList.add(size);
      }
      return sizeArray.length;
    }
  }
}
